import time
import socket
from typing import Optional, List, Dict
import consul
from consul import ConsulException

class ConsulService:
    """Consul服务注册与发现工具类"""
    def __init__(self, host: str = "localhost", port: int = 8500):
        self.consul = consul.Consul(host=host, port=port)
        self.service_id = None  # 当前服务的ID（用于注销）

    def get_local_ip(self) -> str:
        """获取本地IP（用于服务注册）"""
        try:
            # 连接外部地址获取本地IP（不实际建立连接）
            with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
                s.connect(("8.8.8.8", 80))
                return s.getsockname()[0]
        except Exception:
            return "127.0.0.1"

    def register_service(
        self,
        service_name: str,
        service_port: int,
        tags: Optional[List[str]] = None,
        interval: str = "10s",  # 健康检查间隔
        timeout: str = "5s"     # 健康检查超时
    ) -> bool:
        """注册服务到Consul"""
        tags = tags or []
        ip = self.get_local_ip()
        self.service_id = f"{service_name}-{ip}-{service_port}"  # 唯一服务ID

        # 健康检查（HTTP接口，服务需提供/health端点）
        check = consul.Check.http(
            url=f"http://{ip}:{service_port}/health",
            interval=interval,
            timeout=timeout
        )

        try:
            self.consul.agent.service.register(
                name=service_name,
                service_id=self.service_id,
                address=ip,
                port=service_port,
                tags=tags,
                check=check
            )
            print(f"服务注册成功：{service_name}（{ip}:{service_port}）")
            return True
        except ConsulException as e:
            print(f"服务注册失败：{str(e)}")
            return False

    def discover_service(self, service_name: str) -> Optional[List[Dict]]:
        """发现指定服务的所有健康实例"""
        try:
            _, instances = self.consul.health.service(service_name, passing=True)
            if not instances:
                print(f"未发现可用的{service_name}服务实例")
                return None
            # 提取实例信息（地址、端口）
            return [
                {
                    "host": instance["Service"]["Address"],
                    "port": instance["Service"]["Port"],
                    "service_id": instance["Service"]["ID"]
                }
                for instance in instances
            ]
        except ConsulException as e:
            print(f"服务发现失败：{str(e)}")
            return None

    def deregister_service(self) -> bool:
        """从Consul注销当前服务"""
        if not self.service_id:
            print("未注册的服务，无需注销")
            return True
        try:
            self.consul.agent.service.deregister(self.service_id)
            print(f"服务注销成功：{self.service_id}")
            return True
        except ConsulException as e:
            print(f"服务注销失败：{str(e)}")
            return False

# 单例实例（默认连接本地Consul）
consul_service = ConsulService()
